@imenam/mcp-documentor 1.0.44 → 1.0.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/src/gui-worker.js +173 -1
  2. package/dist/src/index.js +18 -0
  3. package/dist/src/tools/upload-image.d.ts +14 -0
  4. package/dist/src/tools/upload-image.js +66 -0
  5. package/dist/src/version.d.ts +1 -1
  6. package/dist/src/version.js +1 -1
  7. package/gui/dist/assets/{arc-Ce3Gb8xA.js → arc-BKRFpV_X.js} +1 -1
  8. package/gui/dist/assets/architectureDiagram-3BPJPVTR-g3ix86w4.js +36 -0
  9. package/gui/dist/assets/blockDiagram-GPEHLZMM-DJp0RySg.js +132 -0
  10. package/gui/dist/assets/{c4Diagram-AHTNJAMY-WNjVDfrm.js → c4Diagram-AAUBKEIU-Dv19Wb0P.js} +1 -1
  11. package/gui/dist/assets/channel-BrniWeCv.js +1 -0
  12. package/gui/dist/assets/{chunk-EDXVE4YY-Dg6HQynX.js → chunk-2J33WTMH-BBsfTgNR.js} +1 -1
  13. package/gui/dist/assets/{chunk-4BX2VUAB-DiqlRlBf.js → chunk-4BX2VUAB-CSXLRZh_.js} +1 -1
  14. package/gui/dist/assets/{chunk-55IACEB6-w5vdVSko.js → chunk-55IACEB6-BvPtr-ne.js} +1 -1
  15. package/gui/dist/assets/chunk-727SXJPM-CWUhOtR-.js +206 -0
  16. package/gui/dist/assets/chunk-AQP2D5EJ-BQ0HicF_.js +231 -0
  17. package/gui/dist/assets/{chunk-FMBD7UC4-B_8Ah5kO.js → chunk-FMBD7UC4-jHVVH30s.js} +1 -1
  18. package/gui/dist/assets/{chunk-YZCP3GAM-UAMyKnC1.js → chunk-ND2GUHAM-Bpfb395X.js} +1 -1
  19. package/gui/dist/assets/{chunk-QZHKN3VN-3KYhwfha.js → chunk-QZHKN3VN-Dx2Yi2S_.js} +1 -1
  20. package/gui/dist/assets/classDiagram-4FO5ZUOK-B8_yXQAM.js +1 -0
  21. package/gui/dist/assets/classDiagram-v2-Q7XG4LA2-B8_yXQAM.js +1 -0
  22. package/gui/dist/assets/{cose-bilkent-S5V4N54A-DClmwFbl.js → cose-bilkent-S5V4N54A-Ds421Gqq.js} +1 -1
  23. package/gui/dist/assets/dagre-BM42HDAG-DlN4DvzI.js +4 -0
  24. package/gui/dist/assets/diagram-2AECGRRQ-egBqkNYN.js +43 -0
  25. package/gui/dist/assets/diagram-5GNKFQAL-De9QbkXT.js +10 -0
  26. package/gui/dist/assets/diagram-KO2AKTUF-B7ViWsaJ.js +3 -0
  27. package/gui/dist/assets/diagram-LMA3HP47-CWI-hnKY.js +24 -0
  28. package/gui/dist/assets/{diagram-G4DWMVQ6-uNQmnOVi.js → diagram-OG6HWLK6-qstINSVL.js} +2 -2
  29. package/gui/dist/assets/{erDiagram-SMLLAGMA-9vfXUDTU.js → erDiagram-TEJ5UH35-CH3pg4ub.js} +1 -1
  30. package/gui/dist/assets/{flowDiagram-DWJPFMVM-BKu8hLQt.js → flowDiagram-I6XJVG4X-DGKis5au.js} +1 -1
  31. package/gui/dist/assets/{ganttDiagram-T4ZO3ILL-JKTpXhdp.js → ganttDiagram-6RSMTGT7-BiD0e5Ub.js} +4 -4
  32. package/gui/dist/assets/gitGraphDiagram-PVQCEYII-7LNV7Qnv.js +106 -0
  33. package/gui/dist/assets/graph--OzhPTMs.js +1 -0
  34. package/gui/dist/assets/{index-BzyTjtNB.css → index-BYVxYY90.css} +1 -1
  35. package/gui/dist/assets/{index-CaPQpXd3.js → index-DBOt1LJt.js} +122 -123
  36. package/gui/dist/assets/infoDiagram-5YYISTIA-CDjlLZyM.js +2 -0
  37. package/gui/dist/assets/{ishikawaDiagram-UXIWVN3A-Cf7vBj2E.js → ishikawaDiagram-YF4QCWOH-if4ogb8U.js} +1 -1
  38. package/gui/dist/assets/{journeyDiagram-VCZTEJTY-DtC9ymAy.js → journeyDiagram-JHISSGLW-DOMmF1XD.js} +1 -1
  39. package/gui/dist/assets/{kanban-definition-6JOO6SKY-O0fDNBIn.js → kanban-definition-UN3LZRKU-BeqZERBX.js} +1 -1
  40. package/gui/dist/assets/layout-SsrduOYp.js +1 -0
  41. package/gui/dist/assets/{linear-Cn1ygZ55.js → linear-BKJMMNN0.js} +1 -1
  42. package/gui/dist/assets/{mindmap-definition-QFDTVHPH-BJkWNcu5.js → mindmap-definition-RKZ34NQL-B2MDEpXz.js} +9 -9
  43. package/gui/dist/assets/pieDiagram-4H26LBE5-Cykp2K6j.js +30 -0
  44. package/gui/dist/assets/quadrantDiagram-W4KKPZXB-DLczui3d.js +7 -0
  45. package/gui/dist/assets/{requirementDiagram-MS252O5E-D7JQGgq0.js → requirementDiagram-4Y6WPE33-VbvufLF4.js} +1 -1
  46. package/gui/dist/assets/sankeyDiagram-5OEKKPKP-BUOiIMns.js +40 -0
  47. package/gui/dist/assets/sequenceDiagram-3UESZ5HK-CB63G6iO.js +162 -0
  48. package/gui/dist/assets/stateDiagram-AJRCARHV-DvGDV-mj.js +1 -0
  49. package/gui/dist/assets/stateDiagram-v2-BHNVJYJU-CSlYTx4_.js +1 -0
  50. package/gui/dist/assets/{timeline-definition-GMOUNBTQ-BSd1iHP7.js → timeline-definition-PNZ67QCA-DVi9QtSX.js} +1 -1
  51. package/gui/dist/assets/{vennDiagram-DHZGUBPP-5vVRkiC1.js → vennDiagram-CIIHVFJN-BBbj4Tef.js} +5 -5
  52. package/gui/dist/assets/wardley-L42UT6IY-Ni3IxkS6.js +161 -0
  53. package/gui/dist/assets/wardleyDiagram-YWT4CUSO-8K4ncLPD.js +78 -0
  54. package/gui/dist/assets/{xychartDiagram-5P7HB3ND-CKHTns95.js → xychartDiagram-2RQKCTM6-glUaKKLx.js} +1 -1
  55. package/gui/dist/index.html +2 -2
  56. package/package.json +2 -1
  57. package/gui/dist/assets/_baseUniq-BU0U623P.js +0 -1
  58. package/gui/dist/assets/architectureDiagram-Q4EWVU46-Ces_mPGF.js +0 -36
  59. package/gui/dist/assets/blockDiagram-DXYQGD6D-B8Y-pXgj.js +0 -132
  60. package/gui/dist/assets/channel-Bawra3aZ.js +0 -1
  61. package/gui/dist/assets/chunk-4TB4RGXK-CxKEFtUX.js +0 -206
  62. package/gui/dist/assets/chunk-OYMX7WX6-BT0nXoHz.js +0 -231
  63. package/gui/dist/assets/classDiagram-6PBFFD2Q-A3ottNSQ.js +0 -1
  64. package/gui/dist/assets/classDiagram-v2-HSJHXN6E-A3ottNSQ.js +0 -1
  65. package/gui/dist/assets/clone-mIFDnjwl.js +0 -1
  66. package/gui/dist/assets/dagre-KV5264BT-CTaJghw8.js +0 -4
  67. package/gui/dist/assets/diagram-5BDNPKRD-DDL2xiIH.js +0 -10
  68. package/gui/dist/assets/diagram-MMDJMWI5-Cd2q0xCp.js +0 -43
  69. package/gui/dist/assets/diagram-TYMM5635-f5gxEjq1.js +0 -24
  70. package/gui/dist/assets/gitGraphDiagram-UUTBAWPF-WPLTQc61.js +0 -106
  71. package/gui/dist/assets/graph-BaMEnwCR.js +0 -1
  72. package/gui/dist/assets/infoDiagram-42DDH7IO-VapOHi4Y.js +0 -2
  73. package/gui/dist/assets/layout-CKm9GbtU.js +0 -1
  74. package/gui/dist/assets/min-CVVJHMPl.js +0 -1
  75. package/gui/dist/assets/pieDiagram-DEJITSTG-DBvmgJfB.js +0 -30
  76. package/gui/dist/assets/quadrantDiagram-34T5L4WZ-vWwN725k.js +0 -7
  77. package/gui/dist/assets/sankeyDiagram-XADWPNL6-V_OhiBi2.js +0 -10
  78. package/gui/dist/assets/sequenceDiagram-FGHM5R23-C7-ndrI7.js +0 -157
  79. package/gui/dist/assets/stateDiagram-FHFEXIEX-DtqD-GG8.js +0 -1
  80. package/gui/dist/assets/stateDiagram-v2-QKLJ7IA2-DhNiUVPk.js +0 -1
  81. package/gui/dist/assets/wardley-RL74JXVD-Dd64Tq4P.js +0 -162
  82. package/gui/dist/assets/wardleyDiagram-NUSXRM2D-r6Y_JsSV.js +0 -20
@@ -6,10 +6,14 @@ import { ProxyClient } from "@imenam/mcp-gui-interface";
6
6
  import { IPCMessageSchema } from "../shared/schemas/doc.schema.js";
7
7
  import path from "path";
8
8
  import fs from "fs";
9
+ import { execFile } from "child_process";
10
+ import { promisify } from "util";
11
+ const execFileAsync = promisify(execFile);
9
12
  import { fileURLToPath } from "url";
10
13
  import { createLogger, setupLogging } from "@imenam/mcp-gui-interface";
11
14
  import matter from "gray-matter";
12
15
  import JSZip from "jszip";
16
+ import puppeteer from "puppeteer-core";
13
17
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
14
18
  function findProjectRoot(startDir) {
15
19
  let current = startDir;
@@ -48,6 +52,53 @@ const parentCheckInterval = setInterval(() => {
48
52
  process.exit(0);
49
53
  }
50
54
  }, 2000);
55
+ // undefined = not yet resolved ; null = not found ; string = path found
56
+ let cachedBrowserPath = undefined;
57
+ async function findSystemBrowser() {
58
+ if (cachedBrowserPath !== undefined)
59
+ return cachedBrowserPath;
60
+ const envPath = process.env.CHROMIUM_PATH?.trim();
61
+ if (envPath) {
62
+ if (fs.existsSync(envPath)) {
63
+ cachedBrowserPath = envPath;
64
+ return envPath;
65
+ }
66
+ logger.warn(`CHROMIUM_PATH is set but the file does not exist: ${envPath}`);
67
+ }
68
+ const candidates = [];
69
+ if (process.platform === 'win32') {
70
+ candidates.push('C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe', 'C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe', 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe');
71
+ }
72
+ else if (process.platform === 'darwin') {
73
+ candidates.push('/Applications/Google Chrome.app/Contents/MacOS/Google Chrome');
74
+ }
75
+ else {
76
+ candidates.push('/usr/bin/google-chrome', '/usr/bin/google-chrome-stable', '/usr/bin/chromium', '/usr/bin/chromium-browser', '/snap/bin/chromium');
77
+ }
78
+ for (const p of candidates) {
79
+ if (fs.existsSync(p)) {
80
+ cachedBrowserPath = p;
81
+ return p;
82
+ }
83
+ }
84
+ if (process.platform !== 'win32') {
85
+ for (const bin of ['google-chrome', 'google-chrome-stable', 'chromium', 'chromium-browser']) {
86
+ try {
87
+ const { stdout } = await execFileAsync('which', [bin]);
88
+ const result = stdout.trim();
89
+ if (result) {
90
+ cachedBrowserPath = result;
91
+ return result;
92
+ }
93
+ }
94
+ catch { /* not found */ }
95
+ }
96
+ }
97
+ cachedBrowserPath = null;
98
+ return null;
99
+ }
100
+ let localPort = 0;
101
+ let guiPublicUrl = '';
51
102
  const app = new Hono();
52
103
  let proxyClient = null;
53
104
  const sseControllers = new Set();
@@ -439,6 +490,123 @@ app.get("/api/export-zip/:id", async (c) => {
439
490
  },
440
491
  });
441
492
  });
493
+ // PDF generation
494
+ app.get("/api/pdf", async (c) => {
495
+ const project = c.req.query('project');
496
+ const docId = c.req.query('docId');
497
+ const scale = Math.min(2, Math.max(0.1, Number(c.req.query('scale') ?? '1')));
498
+ if (!project || !docId) {
499
+ return c.json({ error: 'project and docId are required' }, 400);
500
+ }
501
+ const executablePath = await findSystemBrowser();
502
+ if (!executablePath) {
503
+ return c.json({
504
+ error: 'no_browser',
505
+ message: 'Aucun navigateur (Chrome, Edge ou Chromium) n\'a été trouvé sur ce système. Installez Google Chrome ou Chromium pour activer la génération PDF.',
506
+ }, 503);
507
+ }
508
+ const encodedPath = docId.split('/').map(encodeURIComponent).join('/');
509
+ // ?__pdf=1 force <base href="/"> côté serveur pour que les assets JS chargent correctement
510
+ // sans passer par le proxy (qui requiert une auth)
511
+ const url = `http://localhost:${localPort}/?__pdf=1#/${encodeURIComponent(project)}/${encodedPath}`;
512
+ let browser;
513
+ try {
514
+ browser = await puppeteer.launch({
515
+ executablePath,
516
+ headless: true,
517
+ args: ['--no-sandbox', '--disable-setuid-sandbox'],
518
+ });
519
+ const page = await browser.newPage();
520
+ await page.emulateMediaType('print');
521
+ await page.goto(url, { waitUntil: 'load', timeout: 15000 });
522
+ await page.waitForFunction(() => !!window.__pdfReady && (window.__mermaidPending ?? 0) === 0, { timeout: 15000 });
523
+ const pdfBuffer = await page.pdf({
524
+ format: 'A4',
525
+ scale,
526
+ printBackground: false,
527
+ margin: { top: '20mm', bottom: '20mm', left: '15mm', right: '15mm' },
528
+ });
529
+ return new Response(Buffer.from(pdfBuffer), {
530
+ status: 200,
531
+ headers: {
532
+ 'Content-Type': 'application/pdf',
533
+ 'Content-Disposition': `attachment; filename="${encodeURIComponent(docId.split('/').pop() ?? 'document')}.pdf"`,
534
+ },
535
+ });
536
+ }
537
+ catch (err) {
538
+ logger.error(`PDF generation failed: ${err.message}`);
539
+ return c.json({ error: 'pdf_generation_failed', message: err.message }, 500);
540
+ }
541
+ finally {
542
+ if (browser)
543
+ await browser.close();
544
+ }
545
+ });
546
+ // --- Images ---
547
+ const IMAGE_MIME = {
548
+ png: "image/png",
549
+ jpg: "image/jpeg",
550
+ jpeg: "image/jpeg",
551
+ gif: "image/gif",
552
+ webp: "image/webp",
553
+ svg: "image/svg+xml",
554
+ };
555
+ function sanitizeImageFilename(name) {
556
+ return name.replace(/[^a-zA-Z0-9._-]/g, "_");
557
+ }
558
+ function resolveImageFilename(assetsDir, baseName) {
559
+ const safe = sanitizeImageFilename(baseName);
560
+ if (!fs.existsSync(path.join(assetsDir, safe)))
561
+ return safe;
562
+ const ext = path.extname(safe);
563
+ const base = path.basename(safe, ext);
564
+ let i = 1;
565
+ while (fs.existsSync(path.join(assetsDir, `${base}-${i}${ext}`)))
566
+ i++;
567
+ return `${base}-${i}${ext}`;
568
+ }
569
+ app.post("/api/images", async (c) => {
570
+ const project = c.req.query("project");
571
+ if (!project)
572
+ return c.json({ error: "project is required" }, 400);
573
+ let body;
574
+ try {
575
+ body = await c.req.parseBody();
576
+ }
577
+ catch {
578
+ return c.json({ error: "Failed to parse multipart body" }, 400);
579
+ }
580
+ const file = body["file"];
581
+ if (!file || typeof file === "string")
582
+ return c.json({ error: "file field is required" }, 400);
583
+ const assetsDir = path.join(dataDir, "projects", project, "assets");
584
+ fs.mkdirSync(assetsDir, { recursive: true });
585
+ const finalName = resolveImageFilename(assetsDir, file.name ?? "image");
586
+ const buffer = Buffer.from(await file.arrayBuffer());
587
+ fs.writeFileSync(path.join(assetsDir, finalName), buffer);
588
+ return c.json({ url: `/api/images/${project}/${finalName}`, filename: finalName });
589
+ });
590
+ app.get("/api/images/:project", (c) => {
591
+ const project = c.req.param("project");
592
+ const assetsDir = path.join(dataDir, "projects", project, "assets");
593
+ if (!fs.existsSync(assetsDir))
594
+ return c.json([]);
595
+ const files = fs.readdirSync(assetsDir).filter((f) => /\.(png|jpe?g|gif|webp|svg)$/i.test(f));
596
+ return c.json(files.map((f) => ({ filename: f, url: `/api/images/${project}/${f}` })));
597
+ });
598
+ app.get("/api/images/:project/:filename", (c) => {
599
+ const project = c.req.param("project");
600
+ const filename = c.req.param("filename");
601
+ const filePath = path.join(dataDir, "projects", project, "assets", filename);
602
+ if (!fs.existsSync(filePath))
603
+ return c.notFound();
604
+ const ext = path.extname(filename).toLowerCase().slice(1);
605
+ const mime = IMAGE_MIME[ext] ?? "application/octet-stream";
606
+ return new Response(fs.readFileSync(filePath), {
607
+ headers: { "Content-Type": mime },
608
+ });
609
+ });
442
610
  // Static files
443
611
  app.use("/assets/*", serveStatic({ root: path.relative(process.cwd(), absoluteStaticRoot) }));
444
612
  function getHtmlBaseHref(appPath) {
@@ -454,7 +622,9 @@ app.get("/*", (c, next) => {
454
622
  try {
455
623
  const indexPath = path.join(absoluteStaticRoot, "index.html");
456
624
  if (fs.existsSync(indexPath)) {
457
- const baseHref = getHtmlBaseHref(configuredAppPath);
625
+ // ?__pdf=1 : accès direct depuis Puppeteer — pas de préfixe proxy dans <base href>
626
+ const isPdfRender = c.req.query('__pdf') === '1';
627
+ const baseHref = isPdfRender ? '/' : getHtmlBaseHref(configuredAppPath);
458
628
  const html = fs
459
629
  .readFileSync(indexPath, "utf8")
460
630
  .replace("<head>", `<head>\n <base href="${baseHref}" />`);
@@ -504,7 +674,9 @@ async function startServer() {
504
674
  return;
505
675
  }
506
676
  const finalPort = result.port;
677
+ localPort = finalPort;
507
678
  const publicUrl = result.url || `${proxyUrl}${appPath}`;
679
+ guiPublicUrl = publicUrl;
508
680
  logger.info(`Registered with proxy. Public URL: ${publicUrl}, Local Port: ${finalPort}`);
509
681
  const cleanupProxy = async () => {
510
682
  if (proxyClient)
package/dist/src/index.js CHANGED
@@ -37,6 +37,7 @@ import { restoreDocVersion } from "./tools/restore-doc-version.js";
37
37
  import { reindexEmbeddings } from "./tools/reindex-embeddings.js";
38
38
  import { prepareExportBundle } from "./tools/prepare-export-bundle.js";
39
39
  import { deleteExportBundle } from "./tools/delete-export-bundle.js";
40
+ import { uploadImage } from "./tools/upload-image.js";
40
41
  const __filename = fileURLToPath(import.meta.url);
41
42
  const __dirname = path.dirname(__filename);
42
43
  function findProjectRoot(startDir) {
@@ -972,6 +973,21 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
972
973
  required: ["id"],
973
974
  },
974
975
  },
976
+ {
977
+ name: "upload_image",
978
+ description: "Upload an image to a project's assets and get back the markdown link to insert in a document. Provide either 'content' (base64-encoded image) or 'filePath' (absolute path on the server). Returns the URL and a ready-to-use markdown snippet: ![alt](/api/images/{project}/{filename}).",
979
+ inputSchema: {
980
+ type: "object",
981
+ properties: {
982
+ filename: { type: "string", description: "Filename with extension, e.g. 'screenshot.png'" },
983
+ content: { type: "string", description: "Base64-encoded image content (without data: prefix)" },
984
+ filePath: { type: "string", description: "Absolute path to the image file on the server (alternative to content)" },
985
+ project: { type: "string", description: "Target project (defaults to current project)" },
986
+ alt: { type: "string", description: "Alt text for the markdown image link (optional)" },
987
+ },
988
+ required: ["filename"],
989
+ },
990
+ },
975
991
  ],
976
992
  };
977
993
  });
@@ -1041,6 +1057,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1041
1057
  }
1042
1058
  return result;
1043
1059
  }
1060
+ case "upload_image":
1061
+ return await uploadImage(storageEngine, args);
1044
1062
  default:
1045
1063
  throw new Error(`Tool not found: ${name}`);
1046
1064
  }
@@ -0,0 +1,14 @@
1
+ import type { StorageEngine } from "../core/storage-engine.js";
2
+ export declare function uploadImage(storageEngine: StorageEngine, args: unknown): Promise<{
3
+ isError: boolean;
4
+ content: {
5
+ type: string;
6
+ text: string;
7
+ }[];
8
+ } | {
9
+ content: {
10
+ type: string;
11
+ text: string;
12
+ }[];
13
+ isError?: undefined;
14
+ }>;
@@ -0,0 +1,66 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { z } from "zod";
4
+ const UploadImageArgsSchema = z.object({
5
+ filename: z.string().min(1),
6
+ content: z.string().optional(),
7
+ filePath: z.string().optional(),
8
+ project: z.string().optional(),
9
+ alt: z.string().optional(),
10
+ }).refine((d) => d.content !== undefined || d.filePath !== undefined, {
11
+ message: "Either 'content' (base64) or 'filePath' must be provided",
12
+ });
13
+ function sanitizeFilename(name) {
14
+ return name.replace(/[^a-zA-Z0-9._-]/g, "_");
15
+ }
16
+ function resolveFilename(assetsDir, baseName) {
17
+ const safe = sanitizeFilename(baseName);
18
+ if (!fs.existsSync(path.join(assetsDir, safe)))
19
+ return safe;
20
+ const ext = path.extname(safe);
21
+ const base = path.basename(safe, ext);
22
+ let i = 1;
23
+ while (fs.existsSync(path.join(assetsDir, `${base}-${i}${ext}`)))
24
+ i++;
25
+ return `${base}-${i}${ext}`;
26
+ }
27
+ export async function uploadImage(storageEngine, args) {
28
+ try {
29
+ const validated = UploadImageArgsSchema.parse(args);
30
+ const config = storageEngine.getConfig();
31
+ const project = validated.project ?? config.currentProject;
32
+ const assetsDir = path.join(storageEngine.getDataDir(), "projects", project, "assets");
33
+ fs.mkdirSync(assetsDir, { recursive: true });
34
+ const finalName = resolveFilename(assetsDir, validated.filename);
35
+ const targetPath = path.join(assetsDir, finalName);
36
+ if (validated.content !== undefined) {
37
+ const buffer = Buffer.from(validated.content, "base64");
38
+ fs.writeFileSync(targetPath, buffer);
39
+ }
40
+ else {
41
+ const src = validated.filePath;
42
+ if (!fs.existsSync(src)) {
43
+ return {
44
+ isError: true,
45
+ content: [{ type: "text", text: `File not found: ${src}` }],
46
+ };
47
+ }
48
+ fs.copyFileSync(src, targetPath);
49
+ }
50
+ const url = `/api/images/${project}/${finalName}`;
51
+ const alt = validated.alt ?? "";
52
+ const markdownLink = `![${alt}](${url})`;
53
+ return {
54
+ content: [
55
+ {
56
+ type: "text",
57
+ text: `Image uploaded successfully.\nFilename: ${finalName}\nURL: ${url}\nMarkdown: ${markdownLink}`,
58
+ },
59
+ ],
60
+ };
61
+ }
62
+ catch (err) {
63
+ const message = err instanceof Error ? err.message : String(err);
64
+ return { isError: true, content: [{ type: "text", text: `Error uploading image: ${message}` }] };
65
+ }
66
+ }
@@ -1 +1 @@
1
- export declare const APP_VERSION = "1.0.44";
1
+ export declare const APP_VERSION = "1.0.49";
@@ -1,2 +1,2 @@
1
1
  // Auto-generated version file - do not edit manually
2
- export const APP_VERSION = '1.0.44';
2
+ export const APP_VERSION = '1.0.49';
@@ -1 +1 @@
1
- import{a0 as ln,a1 as an,a2 as y,a3 as tn,a4 as H,a5 as q,a6 as _,a7 as un,a8 as rn,a9 as L,aa as o,ab as B,ac as sn,ad as on,ae as fn}from"./index-CaPQpXd3.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,C,a){var O=I-l,i=D-h,n=C-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function W(l,h,I,D,v,A,C){var a=l-I,O=h-D,i=(C?A:-A)/L(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,F=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*L(fn(0,T*T*R-P*P)),j=(P*g-m*S)/R,z=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=j-F,e=z-t,r=w-F,G=p-t;return x*x+e*e>r*r+G*G&&(j=w,z=p),{cx:j,cy:z,x01:-n,y01:-d,x11:j*(v/T-1),y11:z*(v/T-1)}}function hn(){var l=cn,h=yn,I=B(0),D=null,v=gn,A=dn,C=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-an,c=A.apply(this,arguments)-an,F=un(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(F>tn-y)a.moveTo(s*H(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*H(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=F,S=F,j=C.apply(this,arguments)/2,z=j>y&&(D?+D.apply(this,arguments):L(u*u+s*s)),w=_(un(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if(z>y){var G=sn(z/u*q(j)),M=sn(z/s*q(j));(P-=G*2)>y?(G*=t?1:-1,R+=G,T-=G):(P=0,R=T=(f+c)/2),(S-=M*2)>y?(M*=t?1:-1,m+=M,g-=M):(S=0,m=g=(f+c)/2)}var J=s*H(m),K=s*q(m),N=u*H(T),Q=u*q(T);if(w>y){var U=s*H(g),V=s*q(g),X=u*H(R),Y=u*q(R),E;if(F<rn)if(E=pn(J,K,X,Y,U,V,N,Q)){var Z=J-E[0],$=K-E[1],b=U-E[0],k=V-E[1],nn=1/q(on((Z*b+$*k)/(L(Z*Z+$*$)*L(b*b+k*k)))/2),en=L(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=W(X,Y,J,K,s,x,t),r=W(U,V,N,Q,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(J,K),a.arc(0,0,s,m,g,!t)):a.moveTo(J,K),!(u>y)||!(P>y)?a.lineTo(N,Q):p>y?(e=W(N,Q,U,V,u,-p,t),r=W(J,K,X,Y,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-rn/2;return[H(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:B(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:B(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:B(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:B(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:B(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:B(+n),i):A},i.padAngle=function(n){return arguments.length?(C=typeof n=="function"?n:B(+n),i):C},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{a0 as ln,a1 as an,a2 as y,a3 as tn,a4 as H,a5 as q,a6 as _,a7 as un,a8 as rn,a9 as L,aa as o,ab as B,ac as sn,ad as on,ae as fn}from"./index-DBOt1LJt.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,C,a){var O=I-l,i=D-h,n=C-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function W(l,h,I,D,v,A,C){var a=l-I,O=h-D,i=(C?A:-A)/L(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,F=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*L(fn(0,T*T*R-P*P)),j=(P*g-m*S)/R,z=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=j-F,e=z-t,r=w-F,G=p-t;return x*x+e*e>r*r+G*G&&(j=w,z=p),{cx:j,cy:z,x01:-n,y01:-d,x11:j*(v/T-1),y11:z*(v/T-1)}}function hn(){var l=cn,h=yn,I=B(0),D=null,v=gn,A=dn,C=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-an,c=A.apply(this,arguments)-an,F=un(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(F>tn-y)a.moveTo(s*H(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*H(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=F,S=F,j=C.apply(this,arguments)/2,z=j>y&&(D?+D.apply(this,arguments):L(u*u+s*s)),w=_(un(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if(z>y){var G=sn(z/u*q(j)),M=sn(z/s*q(j));(P-=G*2)>y?(G*=t?1:-1,R+=G,T-=G):(P=0,R=T=(f+c)/2),(S-=M*2)>y?(M*=t?1:-1,m+=M,g-=M):(S=0,m=g=(f+c)/2)}var J=s*H(m),K=s*q(m),N=u*H(T),Q=u*q(T);if(w>y){var U=s*H(g),V=s*q(g),X=u*H(R),Y=u*q(R),E;if(F<rn)if(E=pn(J,K,X,Y,U,V,N,Q)){var Z=J-E[0],$=K-E[1],b=U-E[0],k=V-E[1],nn=1/q(on((Z*b+$*k)/(L(Z*Z+$*$)*L(b*b+k*k)))/2),en=L(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=W(X,Y,J,K,s,x,t),r=W(U,V,N,Q,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(J,K),a.arc(0,0,s,m,g,!t)):a.moveTo(J,K),!(u>y)||!(P>y)?a.lineTo(N,Q):p>y?(e=W(N,Q,U,V,u,-p,t),r=W(J,K,X,Y,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-rn/2;return[H(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:B(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:B(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:B(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:B(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:B(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:B(+n),i):A},i.padAngle=function(n){return arguments.length?(C=typeof n=="function"?n:B(+n),i):C},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};